﻿// 版权所有 (c) 2021-2024 duanzt

using Admin.NET.Plugin.ViewFace.Service.Face.Dto;
using Org.BouncyCastle.Utilities;
using SkiaSharp;
using System.Diagnostics;
using System.Drawing;
using ViewFaceCore;
using ViewFaceCore.Core;
using ViewFaceCore.Model;

namespace Admin.NET.Plugin.ViewFace.Service;
[ApiDescriptionSettings(ViewFaceConst.GroupName, Order = 101)]
public class FaceService : IDynamicApiController, ITransient
{

    /// <summary>
    /// 人脸检测
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<DetectOutput> DetectAsync(DetectInput input)
    {
        var dto = new DetectOutput();
        using var paint = new SKPaint
        {
            Color = SKColors.Red,
            Style = SKPaintStyle.Stroke,
            IsAntialias = true,
            StrokeWidth = 2
        };
        //       
        var imageBytes = await FaceUtil.GetFaceData(input.image_type);
        using (var bitmap = SKBitmap.Decode(imageBytes))
        {
            using (FaceDetector faceDetector = new FaceDetector())
            {
                //人脸检测 返回人脸信息集合
                var faceInfos = await faceDetector.DetectAsync(bitmap);
                //
                var canvas = new SKCanvas(bitmap);
                dto.face_num = faceInfos.Count();
                foreach (var (faceInfo, index) in faceInfos.Select((value, i) => (value, i)))
                {
                    //
                    using var faceMark = new FaceLandmarker();
                    var face = new DetectFaceListItem
                    {
                        Location = faceInfo.Location,
                        face_probability = faceInfo.Score,
                        landmark = await faceMark.MarkAsync(bitmap, faceInfo)
                    };

                    //年龄
                    //表情
                    //性别
                    //是否戴眼镜
                    //人脸旋转角度参数

                    // 裁剪人脸小图
                    face.corp_image_base64 = input.display_corp_image != 1 ? "" : FaceUtil.GetCorpImage(bitmap, faceInfo);
                    // 画方框，标记人脸
                    var location = faceInfo.Location;
                    canvas.DrawRect(location.X, location.Y, location.Width, location.Height, paint);
                    canvas.DrawText(index.ToString(), location.X, location.Y, paint);
                    //
                    dto.face_list.Add(face);
                }
            }
            //标注人脸框的图片base64值
            dto.image_base64 = FaceUtil.BitmapToBase64(bitmap);
        }

        return dto;
    }

    /// <summary>
    /// 人脸特征提取
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<ExtractOutput> ExtractAsync(ExtractInput input)
    {
        // base64或url转图片byte数组
        var imagePath0 = await FaceUtil.GetFaceData(input.image_type);
        using var faceImage0 = SKBitmap.Decode(imagePath0);
        //检测人脸信息
        using var faceDetector = new FaceDetector();
        FaceInfo[] infos0 = faceDetector.Detect(faceImage0);
        //标记人脸位置
        using var faceMark = new FaceLandmarker();
        FaceMarkPoint[] points0 = faceMark.Mark(faceImage0, infos0[0]);
        //提取特征值
        using var faceRecognizer = new FaceRecognizer();
        float[] data0 = faceRecognizer.Extract(faceImage0, points0);

        //
        var dto = new ExtractOutput
        {
            extract_base64 = FaceUtil.ConvertToString(data0),
            corp_image = input.display_corp_image != 1 ? "" : FaceUtil.GetCorpImage(faceImage0, infos0[0])
        };

        return dto;
    }
    /// <summary>
    /// 人脸对比
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<MatchOutput> MatchAsync(MatchInput input)
    {
        Stopwatch sw = Stopwatch.StartNew();
        // base64或url转图片byte数组
        var imagePath0 = await FaceUtil.GetFaceData(input.FaceA.image_type);
        var imagePath1 = await FaceUtil.GetFaceData(input.FaceB.image_type);

        using var faceImage0 = SKBitmap.Decode(imagePath0).ToFaceImage();
        using var faceImage1 = SKBitmap.Decode(imagePath1).ToFaceImage();
        //检测人脸信息
        using var faceDetector = new FaceDetector();
        FaceInfo[] infos0 = faceDetector.Detect(faceImage0);
        FaceInfo[] infos1 = faceDetector.Detect(faceImage1);
        //标记人脸位置
        using var faceMark = new FaceLandmarker();
        FaceMarkPoint[] points0 = faceMark.Mark(faceImage0, infos0[0]);
        FaceMarkPoint[] points1 = faceMark.Mark(faceImage1, infos1[0]);
        //提取特征值
        using var faceRecognizer = new FaceRecognizer();
        float[] data0 = faceRecognizer.Extract(faceImage0, points0);
        float[] data1 = faceRecognizer.Extract(faceImage1, points1);

        //对比特征值(是否同一个人)
        //bool isSelf = faceRecognizer.IsSelf(data0, data1);
        //Console.WriteLine($"识别到的人脸是否为同一人：{isSelf}，对比耗时：{sw.ElapsedMilliseconds}ms");

        //相似度
        float similarity = faceRecognizer.Compare(data0, data1);
        string base64String = FaceUtil.ConvertToString(data0);
        float[] data2 = FaceUtil.ConvertToFloatArray(base64String);

        Console.WriteLine();
        sw.Stop();

        //
        var dto = new MatchOutput { score = similarity };

        return dto;
    }
    public async Task SearchAsync()
    {
        await Task.Delay(5000);
    }
}
